package com.juyu.miliao.api.controller;

import com.alipay.api.internal.util.AlipaySignature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.juyu.miliao.api.dao.redis.UserRedisDao;
import com.juyu.miliao.api.domain.CoinPrice;
import com.juyu.miliao.api.domain.Order;
import com.juyu.miliao.api.domain.Vip;
import com.juyu.miliao.api.service.*;
import com.juyu.miliao.api.util.ComputeRedPacketUtil;
import com.juyu.miliao.common.util.DoubleFormatUtil;
import com.juyu.miliao.api.util.XmlUtil;
import com.juyu.miliao.api.util.pay.ZfbPayUtil;
import com.juyu.miliao.common.domain.AlipayConfig;
import com.juyu.miliao.common.domain.CommonHead;
import com.juyu.miliao.common.domain.ConfigWxPay;
import com.juyu.miliao.common.domain.Subject;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.exception.IllegalParamException;
import com.juyu.miliao.common.util.CommonUtil;
import com.juyu.miliao.common.util.VerifyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


@RestController
public class PayController {

    private final Logger payNotifyLogger = LoggerFactory.getLogger("payNotify");
    @Resource
    PayService payService;
    @Resource
    CoinPriceService coinPriceService;
    @Resource
    VipService vipService;
    @Resource
    OrderService orderService;
    @Resource
    WxPayService wxPayService;
    @Resource
    private ConfigAppService configAppService;
    @Resource
    private PackageOnlineService packageOnlineService;
    @Resource
    private ConfigWxPayService configWxPayService;
    @Resource
    private UserRedisDao userRedisDao;

    /**
     * @param payType     支付类型：1支付宝 2 微信
     * @param contentType 计费类型：1金币 2VIP,3:SVIP,4:铂金VIP
     * @param contentId   计费内容查询id
     * @param type 支付类型 0: app支付,1: MWEB--H5支付，2：JSAPI--JSAPI(公众号)，3：JSAPI--JSAPI(小程序)，4：NATIVE--Native支付
     * @param robotOrderType   0-未知(默认)  1-登录机器人   2-注册机器人
     * @param h5OrderType   0-未知(默认)  1-原生app充值   2-h5充值
     * @param payNum   VIP购买个数，默认为1个
     */
    @PostMapping("/pay")
    public String getPay(HttpServletRequest request, Authentication token, @RequestParam("payType") int payType,
                         @RequestParam("contentType") int contentType, @RequestParam("contentId") int contentId,
                         @RequestParam(value = "type",required = false) Integer type,
                         @RequestParam(value = "robotOrderType",required = false) Integer robotOrderType,
                         @RequestParam(value = "h5OrderType",required = false) Integer h5OrderType,
                         @RequestParam(value = "payNum",required = false) Integer payNum) {
        Subject subject = (Subject) token.getPrincipal();
        Long userId = subject.getId();
        if (payType != 1 && payType != 2) {
            throw new IllegalParamException("参数错误");
        }
        if (contentType != 1 && contentType != 2 && contentType!=3 && contentType!=4) {
            throw new IllegalParamException("参数错误");
        }
        //验证请求头 兼容老版本
        CommonHead com = VerifyUtil.verifyCommonHead(request);
        String appPackageId = com.getAppPackageId();
        String channel = com.getChannel();
        String phoneSystem = com.getPhoneSystem();

        /**
         * 如果type 为null设置type值
         */
        if(type==null){
            type=0;
        }
        if(robotOrderType == null){
            robotOrderType = 0;
        }
        if(h5OrderType == null){
            h5OrderType = 1;
        }

        if(payNum == null){
            payNum = 1;
        }
        ConfigWxPay configWxPay = configWxPayService
                .getConfigWxPayByAppPackageIdAndPhoneSystemAndType(appPackageId, Integer.valueOf(phoneSystem),type);
        if(configWxPay == null){
            throw new ConsumeRuntimeException("微信支付通道不存在");
        }
        String temp = "";
        // 商户订单号，商户网站订单系统中唯一订单号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String out_trade_no = ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date());
        // 透传参数
        Map<String, String> params = new HashMap<String, String>();
        params.put("contentType", contentType + "");
        params.put("contentId", contentId + "");
        params.put("userId", userId + "");
        params.put("appPackageId", appPackageId);
        params.put("phoneSystem", phoneSystem + "");
        params.put("wxPayType",type+"");

        ObjectMapper mapper = new ObjectMapper();
        String passback_params = "";
        try {
//            passback_params = URLEncoder.encode(mapper.writeValueAsString(params), "GBK");
            //微信透传参数长度限制不能做encode操作
            passback_params = mapper.writeValueAsString(params);
            if (payType == 1) {
                passback_params = URLEncoder.encode(passback_params, "GBK");
            }
        } catch (Exception e) {
                payNotifyLogger.error("下单透传参数encode出错", e);
        }
        double fee = 0;
        BigDecimal discountFee = new BigDecimal(0+"");
        if (payType == 1) {
            if (contentType == 1) {
                CoinPrice coinPrice = coinPriceService.getCoinPriceById(contentId);
                if (coinPrice == null) {
                    throw new IllegalParamException("参数错误");
                }
                //1.5.5 8元首冲
                if(coinPrice.getCoinNumber() == 800 && userRedisDao.isMemberFirstRechargeUser(userId)){
                    throw new ConsumeRuntimeException("仅首次可充");
                }
                fee = coinPrice.getPrice();
                if(coinPrice.getBoolRandom()==1 && coinPrice.getRandomPrice()>0){
                    double random = DoubleFormatUtil.randomDouble(coinPrice.getRandomPrice());
                    fee = fee - random;
                    discountFee = new BigDecimal(random+"");
                }
                temp = ZfbPayUtil.aliPay(coinPrice.getShowPrice(), "寻寻充值(" + coinPrice.getShowCoin() + ")",
                        out_trade_no + "", fee + "", passback_params);
            } else {
                Vip vip = vipService.getVipById(contentId);
                if (vip == null) {
                    throw new IllegalParamException("参数错误");
                }
                fee = vip.getPrice()*payNum;
                temp = ZfbPayUtil.aliPay(vip.getShowPrice(), "购买寻寻" + vip.getShowDesc(), out_trade_no + "",
                        fee + "", passback_params);
            }
            Order order = new Order();
            order.setUserId(userId);
            order.setContentType(contentType);
            order.setFee(fee);
            order.setOrderId(out_trade_no);
            order.setOrderStatus(2);
            order.setPayType(payType);
            order.setContentId(contentId);
            order.setChannelId(channel);
            order.setPhoneSystem(CommonUtil.null2Int(com.getPhoneSystem()));
            order.setVersionNum(com.getVersionNum());
            order.setAppPackageId(appPackageId);
            order.setGroupType(configAppService.getGroupType(com.getAppPackageId(), com.getPhoneSystem()));
            order.setOnline(packageOnlineService.getOnline(com));
            order.setOutId(out_trade_no);
            order.setConfigPayId(configWxPay.getId()+"");
            order.setRobotOrderType(robotOrderType);
            order.setH5OrderType(h5OrderType);
            order.setDiscountFee(discountFee);
            order.setPayNum(payNum);
            orderService.insertOrder(order);
        }

        if (payType == 2) {
            if (contentType == 1) {
                CoinPrice coinPrice = coinPriceService.getCoinPriceById(contentId);
                if (coinPrice == null) {
                    throw new IllegalParamException("参数错误");
                }
                //1.5.5 8元首冲
                if(coinPrice.getCoinNumber() == 800 && userRedisDao.isMemberFirstRechargeUser(userId)){
                    throw new ConsumeRuntimeException("仅首次可充");
                }
                String desc = "寻寻充值(" + coinPrice.getShowCoin() + ")";
                fee = coinPrice.getPrice();
                if(coinPrice.getBoolRandom()==1 && coinPrice.getRandomPrice()>0){
                    double random = DoubleFormatUtil.randomDouble(coinPrice.getRandomPrice());
                    fee = fee - random;
                    discountFee = new BigDecimal(random+"");
                }
                coinPrice.setPrice(fee);
                temp = wxPayService.getWxPay(request, desc, userId, payType, contentType,
                        coinPrice.getPrice(), discountFee, contentId, passback_params,configWxPay,robotOrderType,h5OrderType
                        ,payNum);
            } else {
                Vip vip = vipService.getVipById(contentId);
                if (vip == null) {
                    throw new IllegalParamException("参数错误");
                }
                String desc = "购买寻寻" + vip.getShowDesc();
                temp = wxPayService.getWxPay(request,desc, userId, payType, contentType,
                        Double.valueOf(vip.getPrice()*payNum),discountFee,contentId, passback_params,
                        configWxPay,robotOrderType,h5OrderType,payNum);
            }
        }
        return temp;
    }

    @PostMapping("/pay/notify/zfb_notify")
    public String zfb_notify(HttpServletRequest request){
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        boolean flag = false;
        String str = "failure";
        try {
            flag = AlipaySignature.rsaCheckV1(params,AlipayConfig.getAlipayPublicKey(),"utf-8","RSA2");
            if (flag) {
                str = payService.zfbNotify(params);
            }
        } catch (Exception e) {
                payNotifyLogger.error("支付宝支付回调错误+", e);
        }
        return str;
    }

    // 微信支付回调
    @PostMapping("/pay/notify/wxPay_notify")
    public String wxPay_notify(HttpServletRequest request){
        String line = "";
        StringBuffer inputString = new StringBuffer();
        String resultStr ="";
        try {
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            request.getReader().close();
            String returnXml = inputString.toString();
            Map<String, String> notifyMap = XmlUtil.parseXml(returnXml);
            resultStr = payService.wxPayNotify(notifyMap);
        } catch (Exception e) {
            payNotifyLogger.error("微信支付回调错误", e);

        }
        return resultStr;
    }
}
